﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Web;
using Pampa.GenericEntity;
using Pampa.Grid.Data;
using Pampa.Grid.UI.CustomControls;
using Pampa.MVC.Helpers;
using Pampa.Grid.Core.Filters;

namespace Pampa.MVC.Fluent.Grid
{
    public class CustomGridBuilder<TEntity> : IHtmlString 
    {
        private string _clientId;
        private string _quickFiltersId;
        private int _pageSize;
        private bool _checkable;

        private string _configEntityName;
        private GridDataReader _gridDataReader;
        private CustomGridConfig<TEntity> _config;
        private readonly AndGroupFilter _staticFilter;

        public CustomGridBuilder()
        {
            _staticFilter = new AndGroupFilter();
        }

        public CustomGridBuilder<TEntity> ClientId(string clientId)
        {
            _clientId = clientId;
            _quickFiltersId = "filters" + _clientId;
            return this;
        }

        public CustomGridBuilder<TEntity> PageSize(int pageSize)
        {
            _pageSize = pageSize;
            return this;
        }

        public CustomGridBuilder<TEntity> Checkable()
        {
            _checkable = true;
            return this;
        }

        public CustomGridBuilder<TEntity> Config(string entityName)
        {
            _configEntityName = entityName;

            if(_gridDataReader != null && _gridDataReader is GenericEntityDataReader)
            {
                ((GenericEntityDataReader) _gridDataReader).Type = entityName;
            }

            return this;
        }

        public CustomGridBuilder<TEntity> DefaultConfig()
        {
            _configEntityName = typeof(TEntity).AssemblyQualifiedName;
            return this;
        }
        
        public CustomGridBuilder<TEntity> Config(CustomGridConfig<TEntity> config)
        {
            if (string.IsNullOrEmpty(_clientId))
            {
                throw new Exception("Client Id must be defined before the config class in the fluent chain.");
            }

            _config = config;
            _config.QuickFilterId = _quickFiltersId;
            _config.Init();

            return this;
        }

        internal CustomGridBuilder<TEntity> DataReader(GridDataReader dataReader)
        {
            _gridDataReader = dataReader;
            return this;
        }

        #region Filter By

        public CustomGridBuilder<TEntity> FilterBy(Filter filter)
        {
            _staticFilter.AddFilter(filter);
            return this;
        }

        public FilterStringBuilder<TEntity> FilterBy(Expression<Func<TEntity, string>> property)
        {
            return new FilterStringBuilder<TEntity>(this, _staticFilter, property);
        }

        public FilterNonStringBuilder<TEntity, int> FilterBy(Expression<Func<TEntity, int>> property)
        {
            return new FilterNonStringBuilder<TEntity, int>(this, _staticFilter, property);
        }

        public FilterNonStringBuilder<TEntity, int?> FilterBy(Expression<Func<TEntity, int?>> property)
        {
            return new FilterNonStringBuilder<TEntity, int?>(this, _staticFilter, property);
        }

        public FilterNonStringBuilder<TEntity, Single> FilterBy(Expression<Func<TEntity, Single>> property)
        {
            return new FilterNonStringBuilder<TEntity, Single>(this, _staticFilter, property);
        }

        public FilterNonStringBuilder<TEntity, Single?> FilterBy(Expression<Func<TEntity, Single?>> property)
        {
            return new FilterNonStringBuilder<TEntity, Single?>(this, _staticFilter, property);
        }

        public FilterNonStringBuilder<TEntity, Double> FilterBy(Expression<Func<TEntity, Double>> property)
        {
            return new FilterNonStringBuilder<TEntity, Double>(this, _staticFilter, property);
        }

        public FilterNonStringBuilder<TEntity, Double?> FilterBy(Expression<Func<TEntity, Double?>> property)
        {
            return new FilterNonStringBuilder<TEntity, Double?>(this, _staticFilter, property);
        }

        public FilterNonStringBuilder<TEntity, Decimal> FilterBy(Expression<Func<TEntity, Decimal>> property)
        {
            return new FilterNonStringBuilder<TEntity, Decimal>(this, _staticFilter, property);
        }

        public FilterNonStringBuilder<TEntity, Decimal?> FilterBy(Expression<Func<TEntity, Decimal?>> property)
        {
            return new FilterNonStringBuilder<TEntity, Decimal?>(this, _staticFilter, property);
        }

        public FilterNonStringBuilder<TEntity, DateTime> FilterBy(Expression<Func<TEntity, DateTime>> property)
        {
            return new FilterNonStringBuilder<TEntity, DateTime>(this, _staticFilter, property);
        }

        public FilterNonStringBuilder<TEntity, DateTime?> FilterBy(Expression<Func<TEntity, DateTime?>> property)
        {
            return new FilterNonStringBuilder<TEntity, DateTime?>(this, _staticFilter, property);
        }

        public FilterUnknownTypeBuilder<TEntity, TProperty> FilterBy<TProperty>(Expression<Func<TEntity, TProperty>> property)
        {
            return new FilterUnknownTypeBuilder<TEntity, TProperty>(this, _staticFilter, property);
        }

        #endregion

        #region ToString

        public string ToHtmlString()
        {
            CustomGrid grid;

            // xml configuration
            if (_configEntityName != null)
            {
                grid = new CustomGrid();

                // generic entities
                if (_gridDataReader != null)
                {
                    grid.DataReader = _gridDataReader;
                }
                // standard entities
                else
                {
                    grid.DataReader = PampaMvc.GetGridDataReader2(_configEntityName);
                }

                grid.LoadEntityConfiguration(_configEntityName);
            }
            // fluent configuration
            else if (_config != null)
            {
                grid = _config.Grid;
            } 
            // no configured grid
            else
            {
                throw new Exception(string.Format("The grid {0} has not been configured", _clientId));
            }

            grid.ID = _clientId;
            grid.Orderable = true;
            grid.CssClass = "customGrid";
            grid.PageSize = _pageSize;
            grid.Checkable = _checkable;

            // if no data reader from the configuration then load the default data grid based on the grid entity type
            if (grid.DataReader == null)
            {
                grid.DataReader = PampaMvc.GetGridDataReader(typeof(TEntity));
            }

            grid.Configuration.StaticFilter = _staticFilter;

            var sb = new StringBuilder();
            
            // includes
            sb.Append(CustomGrid.Includes());

            // quick filter
            if (grid.QuickFilterDefinitions != null && grid.QuickFilterDefinitions.Count > 0)
            {
                var qFilter = new QuickFiltersPanel();
                qFilter.ID = _quickFiltersId;
                qFilter.CssClass = "quickFilters";
                qFilter.Grid = grid;

                sb.Append(qFilter.Render());
            } 
            
            // grid
            sb.Append(grid.Render());

            return sb.ToString();
        }

        public override string ToString()
        {
            return ToHtmlString();
        }

        #endregion
    }
}
